// CodeFinder.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "FindCode.h"
#include "Decode.h"
#include "CheckCode.h"
#include "CropImage.h"
//#include "CheckImage.h"
#include <io.h>
#include <queue>
#include <iostream>
#include <sstream>

/*
queue<IplImage*> g_loadedImages;
queue<std::string> g_filename;*/


int g_switch=0;
int g_filesleft;
//char *g_filepath;
int g_fileCount=0;
bool g_firstfile=true;
//int g_mutex=0;

//test
void testMakeCross(IplImage *normalized, int type, int count)
{
	IplImage *temp = cvCreateImage( cvSize(normalized->width,normalized->height), 8, 3 );
	//ImageUtils::copyRegion(normalized,temp,cvPoint(0,0),cvPoint(temp->width-1,temp->height-1));
	/*for (int i=0; i<temp->height; i++)
	{ 
		for (int j=0; j<temp->width; j++)
		{
			Pixel pix = ImageUtils::getPixel(normalized,j,i,normalized->nChannels);
			ImageUtils::setPixel(temp,pix);
			ImageUtils::setPixelValue(temp,cvPoint(j,i),0,255);
		}
	}*/
	cvConvertImage( normalized, temp, 0 );

	for (int i=0; i<3; i++)
	{
		for (int j=0; j<32; j++)
		{
			for (int k=0; k<6; k++)
			{
				int add=j*2;
				if (type==1)
					add=31;
				int xCoord = 152*i + k*22 + 11;
				int yCoord = j*21.8 + 11;
				CvPoint startPix = cvPoint(xCoord,yCoord);
				cvRectangle( temp, cvPoint(xCoord-11,yCoord-11), cvPoint(xCoord+11,yCoord+11), cvScalar(255,255,255,0),1, 8, 0 );
				if (Decode::getValue(i*32+(-1*(j-add)),k)==1 && k!=5)
				{ 
					cvLine(temp, cvPoint(xCoord,yCoord),cvPoint(xCoord,yCoord), cvScalar(255,100,100,0), 5, 8, 0);
				}
				else if (Decode::getValue(i*32+(-1*(j-add)),k)==1)
				{
					cvLine(temp, cvPoint(xCoord,yCoord),cvPoint(xCoord,yCoord), cvScalar(0,255,0,0), 5, 8, 0);
				}
				else if (Decode::getValue(i*32+(-1*(j-add)),k)==0 && k==5)
				{
					cvLine(temp, cvPoint(xCoord,yCoord),cvPoint(xCoord,yCoord), cvScalar(0,0,255,0), 5, 8, 0);
				}
			}
		}
	}

	if (count == 0)
	{
		cvNamedWindow("Detected Dots 1", 1);
		cvShowImage("Detected Dots 1", temp);
		cvMoveWindow("Detected Dots 1",0,0);
	} else {
		cvNamedWindow("Detected Dots 2", 1);
		cvShowImage("Detected Dots 2", temp);
		cvMoveWindow("Detected Dots 2",temp->width+100,0);
		cvWaitKey(0);
		cvDestroyAllWindows();
	}
	
	cvReleaseImage(&temp);
}





/***********************
** run() - Main Method**
************************/
void run(IplImage *image, std::string filename)
{
	//std::string filename;

	/*
	while (g_filesleft!=0)
		{*/
		if (/*g_loadedImages.size()!=0 ||*/ 1)
		{
			int type, codeAmmount=1;
			

			//Debug::message(">>>  Determine Angle\t\t<<<",Debug::VERBOSE);
			//CheckImage::CheckImageAngle(image);
			//Debug::message(">>>  Determine Image Type\t<<<",Debug::VERBOSE);
			//type = CheckImage::getImageType(image);
			/*
			if (type == 0)
							codeAmmount=(int)(image->width/(image->height/2));
						else if (type == 1)
							codeAmmount=(int)(image->width/(image->height/3));*/
			


			if ((image->width%3700) < 800)
						{
							type=1;
							codeAmmount=(int)(image->width/3700);
						}
						else
						{
							type=0;
							codeAmmount=(int)(image->width/5000);
						}
			
							
			
			if (g_firstfile)
			{
				Debug::message(">>>  Determine Alignment\t\t<<<",Debug::IMPORTANT);
				CropImage::findAlignment(image);
			} 			
			if (Init::getRotateImage())
				CropImage::rotateImage(image);		
			if (g_firstfile)
			{
				Debug::message(">>>  Determine Cutting Lines\t<<<",Debug::IMPORTANT);
				CropImage::findCutLines(image,type, codeAmmount);
				g_firstfile=false;
			} else {
				CropImage::getLeftXValue(image);
			}
			static int i;
																									
			for (i=0; i<codeAmmount; i++)
			{
				IplImage *crop=cvCreateImage( cvSize(440,700), image->depth, image->nChannels );
				IplImage *normalized = cvCloneImage(crop);

				//IplImage *saveImg=cvCloneImage(image);
				Debug::message(">>>  Find Codeblock\t\t<<<",Debug::IMPORTANT);
				FindCode::crop(image, crop, normalized, type, i);	

				Debug::message(">>>  Decode Codeblock\t\t<<<",Debug::IMPORTANT);
				Decode::getDots(crop, normalized, type, filename, i, codeAmmount);
											
				if(Init::getDebug())
				{
					testMakeCross(crop, type,0);
					testMakeCross(normalized, type,1);
					cvWaitKey(0);
					cvDestroyAllWindows();
				}	

				cvReleaseImage(&normalized);
				cvReleaseImage(&crop);
				
				Debug::message(">>>  Saving Image Parts\t\t<<<",Debug::IMPORTANT);
				CropImage::cutImage(image,type,filename, i, codeAmmount);
			}
			cout<<"\n";
			//CropImage::crop(image, type, filename);
			//g_loadedImages.pop();
		}
	//}
}


void loadImage(std::string filename)
{
	/*IplImage* image = cvLoadImage( filename.c_str(), CV_LOAD_IMAGE_ANYDEPTH );
	
	if (Init::getDebug())
	{
		cvNamedWindow(filename.c_str(), 0);
		cvShowImage(filename.c_str(), image);
		cvResizeWindow( filename.c_str(), 279, 553 );
		cvWaitKey(0);
		cvDestroyWindow(filename.c_str());
	}


	std::string datname;
	int datnamePos1=0, datnamePos2=0;
	for(int i=filename.length()-1; i>=0; i--)
	{
		if(filename[i]=='.')
			datnamePos2=i;
		else if (filename[i]=='\\')
		{
			datnamePos1=i+1;
			i=0;
		}
	}
	datname=filename.substr(datnamePos1,datnamePos2-datnamePos1);
					//g_filename.push(datname);
					//g_mutex=0;
	

	Debug::message(">>>  Loading Image Done\t\t<<<",Debug::IMPORTANT);
	run(image, datname);
	cvReleaseImage(&image);*/

	static unsigned int width=0,height=0;
	TIFF* tif= TIFFOpen(filename.c_str(), "r"); 
	//IplImage *image1, *image2;
	IplImage *image;
	size_t npixels;
	uint32 *raster;
	int check = 1;
	std::string datname;
	int datnamePos1=0, datnamePos2=0;
	int test=0;

	//if file can be opened
	if (tif)
	{
		//get width & height
		TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &width);           
		TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &height);  
	
		//get image data.
		npixels=width*height;
		raster = (uint32*) _TIFFmalloc(npixels * sizeof (uint32));
	
		//OpenCV can't handle TIFF* => copy from raster to IplImage *image
		if (raster != NULL)
		{
			if (TIFFReadRGBAImage(tif, width, height, raster, 0))
			{
				image = cvCreateImage( cvSize(width,height), IPL_DEPTH_8U, 1 );
				for (int i=0; i<height; i++)
				{
					for (int j=0; j<width; j++)
					{
						(((uchar*)(image->imageData + image->widthStep*((height-i-1)))))[j * image->nChannels] = (uchar)raster[i*width + j];
					}
				}
	
	
				//cvReleaseImage(&image);
				for(int i=filename.length()-1; i>=0; i--)
				{
					if(filename[i]=='.')
						datnamePos2=i;
					else if (filename[i]=='\\')
					{
						datnamePos1=i+1;
						i=0;
					}
				}
				datname=filename.substr(datnamePos1,datnamePos2-datnamePos1);
								
				

				Debug::message(">>>  Loading Image Done\t\t<<<",Debug::IMPORTANT);
				run(image, datname);
				cvReleaseImage(&image);
	
							
			}
		} else {
			cout<<"ERROR: Raster = NULL"<<endl;
		}
		_TIFFfree(raster);
	} 
	TIFFClose(tif);
}



void getFiles()
{
	struct _finddata_t fd;
	intptr_t hFile;
	int done;
	string fname,c;
	fname += Init::getPath();
	fname += "*.tif";

	//if there are files in the directory...
	if ( (hFile = _findfirst(fname.c_str(), &fd )) != -1 )
	{
		done = 0; 
		//...and while there are files left, do...
		while (!done)
		{
			if (!(fd.name[0] == '.' && (fd.name[1] == 0 || fd.name[1] == '.' && fd.name[2] == 0)))
			{
				std::string temp=">>>  Loading Image: ";
				temp+=fd.name;
				temp+="\t<<<";
				Debug::message(temp,Debug::IMPORTANT);

				//give path and filename to loadImage()
				c+=Init::getPath();
				c+=fd.name;
				
				char * c2 = new char[c.length()+1];
				strcpy(c2,c.c_str());
				loadImage(c2);
				c="";
				c2="";
			}
			done = (_findnext(hFile, &fd) != 0);
		}
	}
	g_filesleft = 0;
}



/*
void multithreading()
{
	HANDLE hThread[2];
	DWORD dwID[3];
	DWORD dwRetVal = 0;


	//create threads
	hThread[0] = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)getFiles,NULL,0,&dwID[0]);
	hThread[1] = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)run,NULL,0,&dwID[1]);


	//wait for all threads to complete before continuing
	dwRetVal = WaitForMultipleObjects(2, hThread, TRUE, INFINITE);


	//close handles
	CloseHandle(hThread[0]);
	CloseHandle(hThread[1]);



}*/


//temp
int main(int argc, char* argv[])
{
	if (argc < 2)
	{
		cout<<"Error: No path given!"<<endl;
		system("pause");
	} else {
		TIFFSetWarningHandler(NULL);
		g_filesleft = 1;
		
		//Debug::setLogQuiet();
		Init::setPath(argv[1]);
		//multithreading();

		Init::init("config.txt");
		if (argc>2)
		{
			if (atoi(argv[2])==0)
			{
				Init::setDebug(false);
			} else if (atoi(argv[2])==-1)
			{	
				Init::setDebug(false);
				Debug::setLevel(3);
			}
		} else Init::setDebug(true);

		getFiles();
		// system("pause");
	}
	return 0;
}

